﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using System.Threading;
using OnTheWay.Exceptions;
using OnTheWay.Enums;
using System.Windows.Media;
using System.Windows.Input;

namespace OnTheWay.Functions
{
    public delegate void Task();

    [DesignTimeVisible(false)]
    public class FunctionCtrl : UserControl, IParentPanel, INotifyPropertyChanged
    {
        #region 异步调度

        protected void PostTask(Task task)
        {
            new Thread(() =>
            {
                try
                {
                    task.Invoke();
                    //DispatchMessageStatus = MessageStatusEnum.Success;
                }
                catch (Exception ex)
                {
                    DispatchMessageStatus = MessageStatusEnum.Error;
                    DispatchMessage = "执行任务失败：" + ExceptionHandle.GetMessage(ex);
                }
            }).Start();
        }

        protected void DispatcherInvokeSafety(Action action)
        {
            DispatcherInvokeSafety(action, "FunctionCtrl安全调度（DispatcherSafety）捕获异常");
        }

        protected void DispatcherInvokeSafety(Action action, string msg)
        {
            Dispatcher.Invoke(new Action(() =>
            {
                try
                {
                    action.Invoke();
                }
                catch (Exception ex)
                {
                    DispatchMessageStatus = MessageStatusEnum.Error;
                    DispatchMessage = "安全调度捕获异常：" + ExceptionHandle.GetMessage(ex);
                    ExceptionHandle.Handle(ex, msg);
                }
            }));
        }

        #endregion

        #region 控件入栈
        /// <summary>
        /// 控件入栈容器（后期使用时候代码生成）
        /// </summary>
        private Grid mRootGrid = null;
        //private List<FunctionCtrl> mltStack = null;
        public void FunctionStackPut(FunctionCtrl fun)
        {
            this.InitializeFunctionStack();
            //IFunPanel.FunctionStackPut(fun);
            mRootGrid.Children.Add(fun);
            fun.IFunPanel = this;
        }

        public bool FunctionStackPop()
        {
            this.InitializeFunctionStack();
            UIElementCollection Children = mRootGrid.Children;
            if (Children.Count > 1)
            {
                int index = Children.Count - 1;
                FunctionCtrl ctrl = Children[index] as FunctionCtrl;
                if (ctrl != null)
                {
                    CancelEventArgs e = new CancelEventArgs();
                    ctrl.OnClosing(e);
                    if (e.Cancel == true)
                    {
                        return false;
                    }
                    ctrl.OnClosed(e);
                }
                mRootGrid.Children.RemoveAt(index);
                return true;
            }
            return false;
        }

        public bool CloseFunction(FunctionCtrl ctrl)
        {
            UIElementCollection Children = mRootGrid.Children;
            int index = Children.IndexOf(ctrl);
            if (index >= 0)
            {
                CancelEventArgs e = new CancelEventArgs();
                ctrl.OnClosing(e);
                if (e.Cancel == true)
                {
                    return false;
                }
                ctrl.OnClosed(e);
                mRootGrid.Children.RemoveAt(index);
                return true;
            }
            return false;
        }

        private void InitializeFunctionStack()
        {
            if (mRootGrid == null)
            {
                FrameworkElement content = this.Content as FrameworkElement;
                //while (content.Parent != this)
                //{
                //    content = content.Parent as FrameworkElement;
                //}
                //this.RemoveVisualChild(content);
                //this.AddVisualChild(new Grid() { Background=Brushes.Blue});
                this.Content = null;
                mRootGrid = new Grid();
                mRootGrid.Children.Add(content);
                this.Content = mRootGrid;
            }
        }

        public virtual void OnClosed(EventArgs e)
        {
            if (mRootGrid != null && mRootGrid.Children.Count > 1)
            {
                for (int i = mRootGrid.Children.Count - 1; i > 0; i--)
                {
                    FunctionCtrl fun = mRootGrid.Children[i] as FunctionCtrl;
                    if (fun != null)
                    {
                        fun.OnClosed(e);
                    }
                }
            }
        }

        public virtual void OnClosing(CancelEventArgs e)
        {
            if (mRootGrid != null && mRootGrid.Children.Count > 1)
            {
                for (int i = mRootGrid.Children.Count - 1; i > 0; i--)
                {
                    FunctionCtrl fun = mRootGrid.Children[i] as FunctionCtrl;
                    if (fun != null)
                    {
                        fun.OnClosing(e);
                        if (e.Cancel == true)
                        {
                            return;
                        }
                    }
                }
            }
        }


        #endregion

        #region 控件基本属性

        /// <summary>
        /// 父窗口
        /// </summary>
        protected Window ParentWindow { get { return Window.GetWindow(this); } }
        /// <summary>
        /// 控件是否以持久化方式打开
        /// </summary>
        public bool IsDurable { get; set; }
        /// <summary>
        /// 所属的面板
        /// </summary>
        public IParentPanel IFunPanel { get; set; }
        /// <summary>
        /// 功能标题
        /// </summary>
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(FunctionCtrl),
            new UIPropertyMetadata("功能"));

        /// <summary>
        /// 操作反馈消息
        /// </summary>
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set 
            {
                if (Message == value)
                {
                    SetValue(MessageProperty, value+' '); 
                }
                else
                {
                    SetValue(MessageProperty, value); 
                }
            }
        }
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(FunctionCtrl),
            new UIPropertyMetadata("就绪"));

        //MessageStatusEnum MessageStatus


        public MessageStatusEnum MessageStatus
        {
            get { return (MessageStatusEnum)GetValue(MessageStatusProperty); }
            set { SetValue(MessageStatusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MessageStatus.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MessageStatusProperty =
            DependencyProperty.Register("MessageStatus", typeof(MessageStatusEnum),
            typeof(FunctionCtrl), new UIPropertyMetadata(MessageStatusEnum.Message));


        #endregion

        #region 异步基本属性

        /// <summary>
        /// 功能标题
        /// </summary>
        public string DispatchTitle
        {
            get
            {
                string title = "";
                Dispatcher.Invoke(new Action(() =>
                {
                    title = Title;
                }));
                return title;
            }
            set
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    Title = value;
                }));
            }
        }

        /// <summary>
        /// 操作反馈消息
        /// </summary>
        public string DispatchMessage
        {
            get
            {
                string message = "";
                Dispatcher.Invoke(new Action(() =>
                {
                    message = Message;
                }));
                return message;
            }
            set
            {
                Dispatcher.Invoke(new Action(() =>
                {
                    Message = value;
                }));
            }
        }

        /// <summary>
        /// 操作消息状态
        /// </summary>
        public MessageStatusEnum DispatchMessageStatus
        {
            get
            {
                MessageStatusEnum status = MessageStatusEnum.Message;
                Dispatcher.Invoke(new Action(() =>
                {
                    status = MessageStatus;
                }));
                return status;
            }
            set
            {
                Dispatcher.Invoke(new Action(() => this.MessageStatus = value));
            }
        }
        
        #endregion

        #region 改变事件

        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 通知属性改变
        /// </summary>
        /// <param name="name"></param>
        public virtual void PropertyNotifyChanged(String name)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
        /// <summary>
        /// 通知属性改变
        /// </summary>
        /// <param name="name"></param>
        public void DispatchPropertyNotifyChanged(String name)
        {
            if (this.PropertyChanged != null)
            {
                Dispatcher.Invoke(new Action(() => { PropertyChanged(this, new PropertyChangedEventArgs(name)); }));
            }
        }

        #endregion 改变事件

        #region 画面缩放

        private ScaleTransform mScaleTransform = new ScaleTransform();

        public ScaleTransform ScaleTransform
        {
            get { return mScaleTransform; }
            set { mScaleTransform = value; PropertyNotifyChanged("ScaleTransform"); }
        }

        protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
        {
            base.OnPreviewMouseWheel(e);
            if (Keyboard.IsKeyDown(Key.LeftCtrl)||Keyboard.IsKeyDown(Key.RightCtrl))
            {
                double exp = Math.Pow(1.0001, e.Delta);
                ScaleTransform.ScaleX *= exp;
                ScaleTransform.ScaleY *= exp;
                e.Handled = true;
            }
        }

        #endregion

    }
}
